From 3bd51183a899978e2b868e185183521f8c577588 Mon Sep 17 00:00:00 2001 From: Kristian Rietveld Date: Tue, 20 Mar 2007 12:32:19 +0000 Subject: [PATCH] add _gtk_tree_view_column_get_focus_area(). 2007-03-20 Kristian Rietveld * gtk/gtktreeviewcolumn.c: * gtk/gtktreeprivate.h: add _gtk_tree_view_column_get_focus_area(). * gtk/gtktreeview.c (gtk_tree_view_clamp_column_visible): add focus_to_cell parameter, rework to handle clamping columns which are bigger than the available page size better, (gtk_tree_view_key_press): remove code handling moving the focus to other column headers, (gtk_tree_view_header_focus): add clamp_column_visible parameter, fix RTL support, don't wrap around when moving focus to other column headers, call gtk_tree_view_clamp_column_visible() instead of duplicating code, (gtk_tree_view_focus): only clamp the column visible when we are explicitly moving to another column header (fixes #399555, Charles Kerr), (gtk_tree_view_move_cursor_left_right): update call to gtk_tree_view_clamp_column_visible(). svn path=/trunk/; revision=17546 --- ChangeLog | 20 +++++ gtk/gtktreeprivate.h | 4 + gtk/gtktreeview.c | 192 ++++++++++++++++++---------------------- gtk/gtktreeviewcolumn.c | 18 ++++ 4 files changed, 129 insertions(+), 105 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6b673df04b..ba24fd1100 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2007-03-20 Kristian Rietveld + + * gtk/gtktreeviewcolumn.c: + * gtk/gtktreeprivate.h: add _gtk_tree_view_column_get_focus_area(). + + * gtk/gtktreeview.c (gtk_tree_view_clamp_column_visible): add + focus_to_cell parameter, rework to handle clamping columns which + are bigger than the available page size better, + (gtk_tree_view_key_press): remove code handling moving the focus + to other column headers, + (gtk_tree_view_header_focus): add clamp_column_visible parameter, + fix RTL support, don't wrap around when moving focus to other + column headers, call gtk_tree_view_clamp_column_visible() instead + of duplicating code, + (gtk_tree_view_focus): only clamp the column visible when we are + explicitly moving to another column header (fixes #399555, Charles + Kerr), + (gtk_tree_view_move_cursor_left_right): update call to + gtk_tree_view_clamp_column_visible(). + 2007-03-19 Matthias Clasen * demos/gtk-demo/appwindow.c: Explicitly set the title on the diff --git a/gtk/gtktreeprivate.h b/gtk/gtktreeprivate.h index 0e0a332f0e..696005828a 100644 --- a/gtk/gtktreeprivate.h +++ b/gtk/gtktreeprivate.h @@ -409,6 +409,10 @@ void _gtk_tree_view_column_cell_render (GtkTreeViewColumn *tree_column, GdkRectangle *cell_area, GdkRectangle *expose_area, guint flags); +void _gtk_tree_view_column_get_focus_area (GtkTreeViewColumn *tree_column, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *focus_area); gboolean _gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column, gint direction, gboolean left, diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index e1436dacad..b97782482e 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -352,7 +352,8 @@ static void gtk_tree_view_clamp_node_visible (GtkTreeView GtkRBTree *tree, GtkRBNode *node); static void gtk_tree_view_clamp_column_visible (GtkTreeView *tree_view, - GtkTreeViewColumn *column); + GtkTreeViewColumn *column, + gboolean focus_to_cell); static gboolean gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view, GdkEventMotion *event); static void gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view); @@ -5087,7 +5088,6 @@ gtk_tree_view_key_press (GtkWidget *widget, if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE)) { GList *focus_column; - gint focus_column_width = 0; gboolean rtl; rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL); @@ -5100,9 +5100,6 @@ gtk_tree_view_key_press (GtkWidget *widget, if (GTK_WIDGET_HAS_FOCUS (column->button)) break; - - if (column->visible) - focus_column_width += GTK_TREE_VIEW_COLUMN (column)->width; } if (focus_column && @@ -5221,61 +5218,6 @@ gtk_tree_view_key_press (GtkWidget *widget, return TRUE; } - - if (focus_column && - (event->keyval == GDK_Left || event->keyval == GDK_KP_Left - || event->keyval == GDK_Right || event->keyval == GDK_KP_Right)) - { - if ((event->keyval == (rtl ? GDK_Right : GDK_Left) - || event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left))) - { - GList *tmp; - - for (tmp = focus_column->prev; tmp; tmp = tmp->prev) - if (GTK_TREE_VIEW_COLUMN (tmp->data)->visible) - break; - - if (!tmp) - { - gtk_widget_error_bell (widget); - return TRUE; - } - - tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp->data); - gtk_widget_grab_focus (tree_view->priv->focus_column->button); - focus_column_width -= tree_view->priv->focus_column->width; - gtk_adjustment_set_value (tree_view->priv->hadjustment, - CLAMP (focus_column_width, - tree_view->priv->hadjustment->lower, - tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size)); - } - else if ((event->keyval == (rtl ? GDK_Left : GDK_Right) - || event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))) - { - GList *tmp; - - for (tmp = focus_column->next; tmp; tmp = tmp->next) - if (GTK_TREE_VIEW_COLUMN (tmp->data)->visible) - break; - - if (!tmp) - { - gtk_widget_error_bell (widget); - return TRUE; - } - - tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp->data); - - gtk_widget_grab_focus (tree_view->priv->focus_column->button); - focus_column_width += tree_view->priv->focus_column->width; - gtk_adjustment_set_value (tree_view->priv->hadjustment, - CLAMP (focus_column_width, - tree_view->priv->hadjustment->lower, - tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size)); - } - - return TRUE; - } } /* Chain up to the parent class. It handles the keybindings. */ @@ -7578,7 +7520,8 @@ gtk_tree_view_get_fixed_height_mode (GtkTreeView *tree_view) */ static gboolean gtk_tree_view_header_focus (GtkTreeView *tree_view, - GtkDirectionType dir) + GtkDirectionType dir, + gboolean clamp_column_visible) { GtkWidget *focus_child; @@ -7619,12 +7562,7 @@ gtk_tree_view_header_focus (GtkTreeView *tree_view, } - rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL); - if (rtl) { - GList *temp = first_column; - first_column = last_column; - last_column = temp; - } + rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL); switch (dir) { @@ -7669,16 +7607,10 @@ gtk_tree_view_header_focus (GtkTreeView *tree_view, if (GTK_TREE_VIEW_COLUMN (tmp_list->data)->button == focus_child) break; - if (tmp_list == first_column && dir == GTK_DIR_LEFT) - { - focus_child = GTK_TREE_VIEW_COLUMN (last_column->data)->button; - gtk_widget_grab_focus (focus_child); - break; - } - else if (tmp_list == last_column && dir == GTK_DIR_RIGHT) - { - focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button; - gtk_widget_grab_focus (focus_child); + if ((tmp_list == first_column && dir == (rtl ? GTK_DIR_RIGHT : GTK_DIR_LEFT)) + || (tmp_list == last_column && dir == (rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT))) + { + gtk_widget_error_bell (GTK_WIDGET (tree_view)); break; } @@ -7686,7 +7618,7 @@ gtk_tree_view_header_focus (GtkTreeView *tree_view, { GtkTreeViewColumn *column; - if (dir == GTK_DIR_RIGHT) + if (dir == (rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT)) tmp_list = tmp_list->next; else tmp_list = tmp_list->prev; @@ -7723,20 +7655,11 @@ gtk_tree_view_header_focus (GtkTreeView *tree_view, break; } - /* If the following isn't true, then the view is smaller then the scrollpane. - */ - if ((focus_child->allocation.x + focus_child->allocation.width) <= - (tree_view->priv->hadjustment->upper)) - { - /* Scroll to the button, if needed */ - if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) < - (focus_child->allocation.x + focus_child->allocation.width)) - gtk_adjustment_set_value (tree_view->priv->hadjustment, - focus_child->allocation.x + focus_child->allocation.width - - tree_view->priv->hadjustment->page_size); - else if (tree_view->priv->hadjustment->value > focus_child->allocation.x) - gtk_adjustment_set_value (tree_view->priv->hadjustment, - focus_child->allocation.x); + if (clamp_column_visible) + { + gtk_tree_view_clamp_column_visible (tree_view, + tree_view->priv->focus_column, + FALSE); } } @@ -7770,7 +7693,7 @@ gtk_tree_view_focus (GtkWidget *widget, { case GTK_DIR_LEFT: case GTK_DIR_RIGHT: - gtk_tree_view_header_focus (tree_view, direction); + gtk_tree_view_header_focus (tree_view, direction, TRUE); return TRUE; case GTK_DIR_TAB_BACKWARD: case GTK_DIR_UP: @@ -7788,14 +7711,14 @@ gtk_tree_view_focus (GtkWidget *widget, /* Case 2. We don't have focus at all. */ if (!GTK_WIDGET_HAS_FOCUS (container)) { - if (!gtk_tree_view_header_focus (tree_view, direction)) + if (!gtk_tree_view_header_focus (tree_view, direction, FALSE)) gtk_widget_grab_focus (widget); return TRUE; } /* Case 3. We have focus already. */ if (direction == GTK_DIR_TAB_BACKWARD) - return (gtk_tree_view_header_focus (tree_view, direction)); + return (gtk_tree_view_header_focus (tree_view, direction, FALSE)); else if (direction == GTK_DIR_TAB_FORWARD) return FALSE; @@ -8832,18 +8755,76 @@ gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view, static void gtk_tree_view_clamp_column_visible (GtkTreeView *tree_view, - GtkTreeViewColumn *column) + GtkTreeViewColumn *column, + gboolean focus_to_cell) { + gint x, width; + if (column == NULL) return; - if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) < - (column->button->allocation.x + column->button->allocation.width)) - gtk_adjustment_set_value (tree_view->priv->hadjustment, - column->button->allocation.x + column->button->allocation.width - - tree_view->priv->hadjustment->page_size); - else if (tree_view->priv->hadjustment->value > column->button->allocation.x) - gtk_adjustment_set_value (tree_view->priv->hadjustment, - column->button->allocation.x); + + x = column->button->allocation.x; + width = column->button->allocation.width; + + if (width > tree_view->priv->hadjustment->page_size) + { + /* The column is larger than the horizontal page size. If the + * column has cells which can be focussed individually, then we make + * sure the cell which gets focus is fully visible (if even the + * focus cell is bigger than the page size, we make sure the + * left-hand side of the cell is visible). + * + * If the column does not have those so-called special cells, we + * make sure the left-hand side of the column is visible. + */ + + if (focus_to_cell && gtk_tree_view_has_special_cell (tree_view)) + { + GtkTreePath *cursor_path; + GdkRectangle background_area, cell_area, focus_area; + + cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); + + gtk_tree_view_get_cell_area (tree_view, + cursor_path, column, &cell_area); + gtk_tree_view_get_background_area (tree_view, + cursor_path, column, + &background_area); + + gtk_tree_path_free (cursor_path); + + _gtk_tree_view_column_get_focus_area (column, + &background_area, + &cell_area, + &focus_area); + + x = focus_area.x; + width = focus_area.width; + + if (width < tree_view->priv->hadjustment->page_size) + { + if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) < (x + width)) + gtk_adjustment_set_value (tree_view->priv->hadjustment, + x + width - tree_view->priv->hadjustment->page_size); + else if (tree_view->priv->hadjustment->value > x) + gtk_adjustment_set_value (tree_view->priv->hadjustment, x); + } + } + + gtk_adjustment_set_value (tree_view->priv->hadjustment, + CLAMP (x, + tree_view->priv->hadjustment->lower, + tree_view->priv->hadjustment->upper + - tree_view->priv->hadjustment->page_size)); + } + else + { + if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) < (x + width)) + gtk_adjustment_set_value (tree_view->priv->hadjustment, + x + width - tree_view->priv->hadjustment->page_size); + else if (tree_view->priv->hadjustment->value > x) + gtk_adjustment_set_value (tree_view->priv->hadjustment, x); + } } /* This function could be more efficient. I'll optimize it if profiling seems @@ -9755,7 +9736,8 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view, gtk_widget_error_bell (GTK_WIDGET (tree_view)); } - gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column); + gtk_tree_view_clamp_column_visible (tree_view, + tree_view->priv->focus_column, TRUE); } static void diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index 585dda2076..12e3942f20 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -3146,6 +3146,24 @@ _gtk_tree_view_column_cell_event (GtkTreeViewColumn *tree_column, path_string); } +void +_gtk_tree_view_column_get_focus_area (GtkTreeViewColumn *tree_column, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *focus_area) +{ + gtk_tree_view_column_cell_process_action (tree_column, + NULL, + background_area, + cell_area, + 0, + CELL_ACTION_FOCUS, + NULL, + focus_area, + NULL, NULL, NULL); +} + + /* cell list manipulation */ static GList * gtk_tree_view_column_cell_first (GtkTreeViewColumn *tree_column) -- 2.30.2